fn main() {
    println!("===============================");
    test01_dangling_references();
    println!("===============================");
    test02_no_dangling_ref();
    println!("===============================");
    test03_cmp_str();
    println!("===============================");
    test04_use_limit();
    println!("===============================");
    test05_struct();
    println!("===============================");
    test06_method();
    println!("===============================");
    test07_complex_use();
    println!("===============================");
}
fn test01_dangling_references() {
    let r = 0;            // ---------+-- 'a
    {                     //          |
        let x = 5;        // -+-- 'b  |
       //r = &x;//err         |       |
    }                     // -+       |
    println!("r: {r}");   //          |
}                         // ---------+
fn test02_no_dangling_ref() {
    let x = 5;            // ----------+-- 'b
    let r = &x;           // --+-- 'a  |
    println!("r: {r}");   //   |       |
}                         // ----------+
fn test03_cmp_str() {
    let string1 = String::from("abcd");
    let string2 = "xyz";

    let result = longest(string1.as_str(), string2);
    println!("The longest string is {result}");
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}
fn test04_use_limit(){
    let string1 = String::from("long string is long");
    let result;

    {
        let string2 = String::from("xyz");
        result = longest(string1.as_str(), string2.as_str());
        println!("The longest string is {result}");
    }
    //println!("The longest string is {result}");//err
}

fn longest_1<'a>(x: &'a str, y: &str) -> &'a str {
    x
}
fn longest_2<'a>(x: &'a str, y: &str) -> &'a str {
    let result = String::from("really long string");
    //result.as_str()//err
    x//dummy
}

fn test05_struct() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().unwrap();
    let i = ImportantExcerpt {
        part: first_sentence,
    };
    println!("{}", i.part);
}
struct ImportantExcerpt<'a> {
    part: &'a str,
}

fn test06_lifetime_elision(){
    let word = first_word("hello world");
    println!("{word}");
}

fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

fn test06_method(){
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().unwrap();
    let i = ImportantExcerpt {
        part: first_sentence,
    };
    println!("{},{}", i.level(),i.announce_and_return_part("hello"));
}

impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }

    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("Attention please: {announcement}");
        self.part
    }
}

fn test07_complex_use(){
    let result = longest_with_an_announcement("hello", "world", "!");
    println!("{result}");
}

use std::fmt::Display;

fn longest_with_an_announcement<'a, T>(
    x: &'a str,
    y: &'a str,
    ann: T,
) -> &'a str
where
    T: Display,
{
    println!("Announcement! {ann}");
    if x.len() > y.len() { x } else { y }
}
